#include "EconomyHome.h"
#include "EconomyPlugin.h"
#include "Managers/GameManager.h"
#include <fstream>
#include "spdlog/fmt/fmt.h"

#include "Network/Client.h"
#include "EconomyAPI.h"
#include "Player/PlayerData.h"
#include "Components/ComponentPlayer.h"
#include "Components/ComponentBody.h"

namespace Economy
{
    static const std::string titleText = "经济";
    constexpr const char *help1 = "\n"
                                  "/ehome    -花钱回到家的位置\n"
                                  "/ehome set    -设置家的位置\n";

    static const std::string normalHelp = help1;



    EconomyHome::~EconomyHome() {}

    void EconomyHome::load()
    {
        m_gameManager = GameSingleton::singletonPtr->getSingleton<GameManager>();
        m_economyAPI = GameSingleton::singletonPtr->getSingleton<EconomyAPI>();

        std::ifstream stream;
        stream.open(fmt::format("{}/EconomyHome.json", EconomyPlugin::PluginDataDirectory));

        if (stream.is_open())
        {
            nlohmann::json jsonData;
            stream >> jsonData;
            Utils::GetJsonValue<uint32_t>(jsonData, m_useMoney, "useMoney", 100);
            Utils::GetJsonValue<std::map<GameGuid, Point3>>(jsonData, m_homeMap, "data", std::map<GameGuid, Point3>());
        }
        else
        {
            m_useMoney = 100;
        }
        stream.close();
    }

    void EconomyHome::save()
    {
        m_homeMapMutex.lock();

        nlohmann::json jsonData = {
            {"useMoney", m_useMoney},
            {"data", m_homeMap}};
        Utils::SaveTextFile(fmt::format("{}/EconomyHome.json", EconomyPlugin::PluginDataDirectory), jsonData.dump());

        m_homeMapMutex.unlock();
    }

    void EconomyHome::setGuidHome(const GameGuid &guid, const Point3 &point)
    {
        m_homeMapMutex.lock();

        auto it = m_homeMap.find(guid);
        if(it != m_homeMap.end())
        {
            it->second = point;
        }
        else
        {
            m_homeMap[guid] = point;
        }

        m_homeMapMutex.unlock();
    }

    bool EconomyHome::getGuidHome(const GameGuid &guid, Point3 &outPoint)
    {
        std::lock_guard<std::mutex> lk(m_homeMapMutex);
        
        auto it = m_homeMap.find(guid);
        if(it != m_homeMap.end())
        {
            outPoint = it->second;
            return true;
        }
        return false;
    }

    void EconomyHome::processCmd(IPlugin::ChatObj &chatObj, std::vector<std::string> &cmdDataVec)
    {
        if(chatObj.m_isTerminal == true)
        {
            chatObj.sendMessage(titleText, "控制台不能使用该指令");
            return;
        }
        if(cmdDataVec.size() == 1)
        {
            Point3 home;
            if(getGuidHome(chatObj.m_client->guid, home))
            {
                // 这种情况在多线程竞争下可能出现数据不准确的情况，不过应该可以无视
                uint32_t money = m_economyAPI->getGuidMoney(chatObj.m_client->guid);
                if(money >= m_useMoney)
                {
                    m_economyAPI->decGuidMoney(chatObj.m_client->guid, m_useMoney);
                    chatObj.m_client->playerData->componentPlayer->setNetPosition(home);
                    chatObj.sendMessage(titleText, fmt::format("回家成功，花费 {} $", m_useMoney));
                }
                else
                {
                    chatObj.sendMessage(titleText, fmt::format("你的钱不够，回家传送一次需要花费 {} $", m_useMoney));
                }
            }
            else
            {
                chatObj.sendMessage(titleText, "你还未设家，没法传送，设家指令：/ehome set ");
            }
            return;
        }
        else if(cmdDataVec.size() > 1 && cmdDataVec[1] == "set")
        {
            Vector3 position;
            chatObj.m_client->playerData->componentPlayer->componentBody->getPosition(position);

            Point3 home = position.toPoint3();
            setGuidHome(chatObj.m_client->guid, home);
            chatObj.sendMessage(titleText, fmt::format("设家成功，回家指令：/ehome，注：需要 {} $", m_useMoney));
            return;
        }
        chatObj.sendMessage(titleText, normalHelp);
    }

}
